package br.com.afi.web.struts.util;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts.Globals;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;

/**
 * Classe responsável por criar Mensagens de Erro ou Sucesso, na camada de apresentação.
 * 
 * @author Tiago Gonçalves
 * @version 1.0
 */
public class Messages
{
	public static final boolean ERROR = true;
	public static final boolean SUCCESS = false;

	private boolean error;
	private List<Message> messages;
	private HttpServletRequest request;

	/**
	 * Construtor padrão.
	 * 
	 * @param request HttpServletRequest Objeto HttpServletRequest da requisição atual(Obrigatório).
	 */
	public Messages( HttpServletRequest request )
	{
		super();
		init( request, error, null );
	}

	/**
	 * Construtor.
	 * 
	 * @param request HttpServletRequest Objeto HttpServletRequest da requisição atual.
	 * @param error boolean True|False, False para mensagens de sucesso, e True para mensagens de
	 *            erro.
	 * @param message String Conteúdo da mensagem a ser exibida.
	 */
	public Messages( HttpServletRequest request, boolean error, String message )
	{
		super();
		init( request, error, message );
	}

	/**
	 * Construtor.
	 * 
	 * @param request HttpServletRequest Objeto HttpServletRequest da requisição atual.
	 * @param error boolean True|False, False para mensagens de sucesso, e True para mensagens de
	 *            erro.
	 * @param messageId String Id da mensagem a ser exibida.
	 * @param message String Conteúdo da mensagem a ser exibida.
	 */
	public Messages( HttpServletRequest request, boolean error, String messageId, String message )
	{
		super();
		init( request, error, messageId, message );
	}

	/**
	 * Método responsável por inicializar as configurações de mensagens.
	 * 
	 * @param request HttpServletRequest Objeto HttpServletRequest da requisição atual.
	 * @param error boolean True|False, True para mensagens de sucesso, e False para mensagens de
	 *            erro.
	 * @param message String Conteúdo da mensagem a ser exibida.
	 */
	private void init( HttpServletRequest request, boolean error, String message )
	{
		this.messages = new ArrayList<Message>();
		this.error = error;
		this.request = request;

		request.removeAttribute( Globals.ERROR_KEY );
		request.removeAttribute( Globals.MESSAGE_KEY );

		addMessage( null, message );
		buildMessages();
	}

	/**
	 * Método responsável por inicializar as configurações de mensagens.
	 * 
	 * @param request HttpServletRequest Objeto HttpServletRequest da requisição atual.
	 * @param error True para mensagens de sucesso, e False para mensagens de erro.
	 * @param messageId Id da mensagem a ser exibida.
	 * @param message Conteúdo da mensagem a ser exibida.
	 */
	private void init( HttpServletRequest request, boolean error, String messageId, String message )
	{
		this.messages = new ArrayList<Message>();
		this.error = error;
		this.request = request;

		request.removeAttribute( Globals.ERROR_KEY );
		request.removeAttribute( Globals.MESSAGE_KEY );

		addMessage( messageId, message );
		buildMessages();
	}

	/**
	 * Método responsável por adicionar uma mensagem de texto, para ser exibiado ao usuário final.
	 * 
	 * @param key Chave do arquivo MessageResource à ser vinculada a mensagem.
	 * @param message Mensagem a ser visualizada pelo usuário.
	 */
	public void addMessage( String key, String message )
	{
		if ( message != null )
		{
			if ( null == key || "".equals( key ) )
				key = "message.detail";

			messages.add( new Message( key, message ) );

			buildMessages();
		}
	}

	/**
	 * Método responsável por adicionar uma mensagem de texto, para um componente específico de
	 * input(UI), para ser exibido ao usuário final.
	 * 
	 * @param id Id do componente(UI)
	 * @param key Chave do arquivo MessageResource à ser vinulada a mensagem.
	 * @param message Mensagem a ser visualizada pelo usuário.
	 */
	public void addMessage( String id, String key, String message )
	{
		if ( null == key || "".equals( key ) )
			key = "message.detail";

		messages.add( new Message( id, key, message ) );

		buildMessages();
	}

	/**
	 * Métoto responsável por criar as mensagens.
	 */
	private void buildMessages()
	{
		if ( !messages.isEmpty() )
		{
			final ActionMessages actionMessages = new ActionMessages();

			for ( Message message : messages )
			{
				if ( message.getId() != null && !"".equals( message.getId() ) )
					actionMessages.add( ActionMessages.GLOBAL_MESSAGE, new ActionMessage( message.getKey(), message.getMessage() ) );
				else
					actionMessages.add( message.getId(), new ActionMessage( message.getKey(), message.getMessage() ) );
			}

			if ( isError() )
			{
				request.setAttribute( Globals.ERROR_KEY, actionMessages );
			}
			else
			{
				request.setAttribute( Globals.MESSAGE_KEY, actionMessages );
			}
		}
	}

	public boolean isError()
	{
		return error;
	}

	public void setError( boolean error )
	{
		this.error = error;
	}

	public List<Message> getMessages()
	{
		return messages;
	}

	public void setMessages( List<Message> messages )
	{
		this.messages = messages;
	}

	public int size()
	{
		return messages.size();
	}

	/**
	 * Classe interna reponsável por representar uma mensagem.
	 */
	private class Message
	{
		private String id;
		private String key;
		private String message;

		public Message( String key, String message )
		{
			super();
			this.key = key;
			this.message = message;
		}

		public Message( String id, String key, String message )
		{
			this( key, message );
			this.id = id;
		}

		public String getId()
		{
			return id;
		}

		public String getMessage()
		{
			return message;
		}

		public String getKey()
		{
			return key;
		}

	}
}
